package view;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.util.ResourceBundle;
import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JTabbedPane;
import model.Model;
import model.turtle.Commandable;


/**
 * Main View section that has the information about the
 *  GUI.
 * @author Angelica Schwartz
 * @author Matthew Roy
 * adapted from EventDemo by Robert Duvall
 */
@SuppressWarnings("serial")
public class MainViewGUI extends JFrame {

    /**
     * acceptable locations for components in the BorderLayout.
     */
    private static final String ACCEPTABLE_POSITIONS =
            "Center North South East West";

    private static final String USER_DIR = "user.dir";
    /**
     * resources package.
     */
    private static final String DEFAULT_RESOURCE_PACKAGE = "resources.";

    /**
     * resources location.
     */
    private ResourceBundle myResources;
    /**
     * language setting.
     */
    private String myLanguage;

    /**
     * used to choose files in user's directory.
     */
    private JFileChooser myChooser;

    /**
     * used to implement multiple workspaces on different tabs.
     */
    private JTabbedPane tabbedPane;
    /**
     * size of the user interface GUI.
     */
    private Dimension size;
    /**
     * Constructs the GUI for SLogo.
     *
     * @param title title that appears in the Frame window's title bar
     * @param s is the initial size of the entire display
     * @param language language in which to display messages
     */
    public MainViewGUI(String title, Dimension s, String language) {
        // set properties of frame
        size = s;
        setTitle(title);
        setSize(size);
        setResizable(false);
        setPreferredSize(size);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        myChooser = new JFileChooser(
                    System.getProperties().getProperty(USER_DIR));
        myLanguage = language;
        myResources = ResourceBundle.getBundle(DEFAULT_RESOURCE_PACKAGE
                                               + myLanguage);
        // set menus and default workspace
        setJMenuBar(makeMenus());
        tabbedPane = new JTabbedPane();
        addWorkspace();

        // display the GUI
        pack();
        setVisible(true);
    }

    /**
     * adds JComponent to the GUI.
     * @param c is the JComponent to be added
     * @param location in the BorderLayout where the
     *      component will be added
     */
    public void addComponent(JComponent c, String location) {
        if (ACCEPTABLE_POSITIONS.contains(location)) {
            getContentPane().add(c, location);
        }
    }

    /**
     * creates a new workspace (displayed as tabs).
     */
    public void addWorkspace() {
        JComponent workspace = new JPanel();
        workspace.setFocusable(true);
        workspace.setLayout(new BorderLayout());
        Model workspaceModel = new Model(new Dimension(3 * size.width / 4, size.height));
        workspace.add(new DrawingScreen(new Dimension(3 * size.width / 4, size.height),
                                        workspaceModel), BorderLayout.CENTER);
        workspace.add(new InformationScreen(new Dimension(size.width, 30),
                                        workspaceModel.getEnvironment()),
                                        BorderLayout.SOUTH);
        workspace.add(new CommandTerminal(new Dimension(400, size.height),
                                        workspaceModel), BorderLayout.EAST);
        tabbedPane.addTab("Workspace " + (tabbedPane.getTabCount() + 1),
                                        workspace);
        add(tabbedPane, BorderLayout.CENTER);
    }
    
    /**
     * changes the language for the SLogo.
     * @param newLanguage is the language to switch to
     */
    public void changeLanguage(String newLanguage) {
        myLanguage = newLanguage;
        myResources = ResourceBundle.getBundle(DEFAULT_RESOURCE_PACKAGE
                                               + myLanguage);
    }

    /**
     * Creates the menu to appear at the top of the frame.
    */
    private JMenuBar makeMenus () {
        JMenuBar result = new JMenuBar();
        result.add(makeFileMenu());
        result.add(makeVisualMenu());
        result.add(makeHelpMenu());
        return result;
    }

   /**
    * Create a File menu that will pop up when the menu button is pressed in the
    * frame.
    *
    * Note, since these classes will not ever be used by any other class, make
    * them inline (i.e., as anonymous inner classes) --- saves making a
    * separate file for one line of actual code.
    */
    private JMenu makeFileMenu () {
        JMenu result = new JMenu(myResources.getString("FileMenu"));
        result.add(new AbstractAction(myResources.getString("SaveCommand")) {
            @Override
            public void actionPerformed (ActionEvent e) {
                String filePath = (String) JOptionPane.showInputDialog(null,
                                                                       "Type your filepath name: ");
                getCurrentCommandTerminal().sendCommand(getCurrentCommandTerminal().getCommandName("SaveCommandPattern")
                                                       + " [ " + filePath + " ]");
            }
        });
        result.add(new AbstractAction(myResources.getString("LoadCommand")) {
            @Override
            public void actionPerformed (ActionEvent e) {
                String filePath = (String) JOptionPane.showInputDialog(null,
                                                       "Type your filepath name: ");
                getCurrentCommandTerminal().sendCommand(getCurrentCommandTerminal().getCommandName("LoadCommandPattern")
                                                       + " [ " + filePath + " ]");
            }
        });
        result.add(new JSeparator());
        result.add(new AbstractAction(myResources.getString("NewWorkspaceCommand")) {
            @Override
            public void actionPerformed (ActionEvent e) {
                addWorkspace();
            }
        });
        result.add(new JSeparator());
        result.add(new AbstractAction(myResources.getString("QuitCommand")) {
            @Override
            public void actionPerformed (ActionEvent e) {
                // end program
                System.exit(0);
            }
        });
        return result;
    }

   /**
    * Creates a menu that changes properties of the pen.
    * @return JMenu
    */
    private JMenu makeVisualMenu() {
        JMenu result = new JMenu(myResources.getString("VisualMenu"));
        result.add(new AbstractAction(myResources.getString("ChangeBackgroundImageCommand")) {
            @Override
            public void actionPerformed (ActionEvent e) {
                int response = myChooser.showOpenDialog(null);
                if (response == JFileChooser.APPROVE_OPTION) {
                    File file =  myChooser.getSelectedFile();
                    getCurrentCommandTerminal().sendCommand(
                              getCurrentCommandTerminal().getCommandName("ChangeBackgroundImagePattern")
                              + " " + file.getPath());
                }
            }
        });
        result.add(new AbstractAction(myResources.getString("RemoveBackgroundImageCommand")) {
            @Override
            public void actionPerformed (ActionEvent e) {              
                getCurrentCommandTerminal().sendCommand(
                              getCurrentCommandTerminal().getCommandName("ChangeBackgroundImagePattern"));
            }
        });
        result.add(new JSeparator());
        result.add(new AbstractAction(myResources.getString("ChangePenDesignCommand")) {
            @Override
            public void actionPerformed (ActionEvent e) {
                String[] choices = Commandable.LINE_DESIGN_CHOICES;
                String newDesign = (String) JOptionPane.showInputDialog(
                                   null, "Choose the new pen design: ",
                                   "Pen Design Choice", JOptionPane.QUESTION_MESSAGE,
                                   null, choices, choices[0]);
                getCurrentCommandTerminal().sendCommand(
                                   getCurrentCommandTerminal().getCommandName("SetPenDesignPattern") + " "
                                   + newDesign);
            }
        });
        result.add(new AbstractAction(myResources.getString("ChangePenThicknessCommand")) {
            @Override
            public void actionPerformed (ActionEvent e) {
                int newThickness = Integer.parseInt(JOptionPane.showInputDialog(getContentPane(),
                                                   "Enter the pen's new thickness (in pixels): "));
                getCurrentCommandTerminal().sendCommand(
                                   getCurrentCommandTerminal().getCommandName("SetPenSizePattern")
                                   + " " + newThickness);
            }
        });
        result.add(new AbstractAction(myResources.getString("SetPenUpCommand")) {
            @Override
            public void actionPerformed (ActionEvent e) {
                getCurrentCommandTerminal().sendCommand(getCurrentCommandTerminal().getCommandName("SetPenUpCommandPattern"));
            }
        });
        result.add(new AbstractAction(myResources.getString("SetPenDownCommand")) {
            @Override
            public void actionPerformed (ActionEvent e) {
                getCurrentCommandTerminal().sendCommand(getCurrentCommandTerminal().getCommandName("SetPenDownCommandPattern"));
            }
        });
       
        return result;
    }
   
    private JMenu makeHelpMenu () {
        JMenu result = new JMenu(myResources.getString("HelpMenu"));
        result.add(new AbstractAction(myResources.getString("ChangeLanguageCommand")) {
            @Override
            public void actionPerformed (ActionEvent e) {
                String[] choices = myResources.getString("LanguagesSupported").split(" ");
                String newLanguage = (String) JOptionPane.showInputDialog(null,
                                         "Choose the new language: ", "Language Setting",
                                         JOptionPane.QUESTION_MESSAGE, null, choices, choices[0]);
                changeLanguage(newLanguage);
                setJMenuBar(makeMenus());
                validate();
                repaint();
                getCurrentCommandTerminal().sendCommand(
                                 getCurrentCommandTerminal().getCommandName("SetLanguageCommandPattern")
                                 + newLanguage);
            }
        });
        result.add(new JSeparator());
        result.add(new AbstractAction(myResources.getString("OpenHelpCommand")) {
            @Override
            public void actionPerformed (ActionEvent e) {
                int response = JOptionPane.showConfirmDialog(null,
                                         "Click OK to show the SLogo Help or "
                                         + "Cancel to return to SLogo", "alert",
                                         JOptionPane.OK_CANCEL_OPTION);
                if (response == JOptionPane.OK_OPTION) {
                    String currentDirectory = System.getProperty(USER_DIR);
                    String url = "file://" + currentDirectory + "/src/resources/help.html";
                    url = url.replace("\\", "/");
                    try {
                        Desktop.getDesktop().browse(URI.create(url));
                    }
                    catch (IOException e1) {
                        JOptionPane.showMessageDialog(null,
                                    "Error loading help file", "alert", JOptionPane.OK_OPTION);
                    }
                }
            }
        });
        return result;
    }

   /**
    * gets the command terminal for this workspace.
    * @return the CommandTerminal
    */
    private CommandTerminal getCurrentCommandTerminal() {
        for (Component c :
            ((JComponent) tabbedPane.getSelectedComponent()).getComponents()) {
            if (CommandTerminal.class.isInstance(c)) {
                return (CommandTerminal) c;
            }
        }
        return null;
    }
}
